﻿using Pfz.Caching;
using Pfz.Threading;

namespace Pfz.DynamicObjects.CloneToModifyModel
{
	/// <summary>
	/// Represents a global (or shared) cache of CloneToModify objects.
	/// </summary>
	/// <typeparam name="TKey">The type of the key contained in the cache.</typeparam>
	/// <typeparam name="TItem">The type of the items contained in the cache.</typeparam>
	public sealed class CtmGlobalCache<TKey, TItem>
	where
		TItem: class, ICtmCacheable<TKey>
	{
		internal YieldReaderWriterLockSlim _modifiableItemsLock;
		internal readonly WeakDictionary<TKey, TItem> _modifiableItems = new WeakDictionary<TKey, TItem>();

		internal readonly WeakDictionary<TKey, TItem> _readOnlyItems = new WeakDictionary<TKey, TItem>();
		
		/// <summary>
		/// Creates a new local (non-shared) cache.
		/// </summary>
		public CtmLocalCache<TKey, TItem> CreateLocalCache()
		{
			return new CtmLocalCache<TKey, TItem>(this);
		}
		
		/// <summary>
		/// Clears the global-cache. Local caches are not affected by this.
		/// </summary>
		public void Clear()
		{
			_modifiableItemsLock.EnterWriteLock();
			try
			{
				_readOnlyItems.Clear();
			}
			finally
			{
				_modifiableItemsLock.ExitWriteLock();
			}
		}
		
		internal TItem _Get(TKey key)
		{
			var result = _readOnlyItems[key];
			
			if (result == null)
			{
				_modifiableItemsLock.EnterReadLock();
				try
				{
					result = _modifiableItems[key];
				}
				finally
				{
					_modifiableItemsLock.ExitReadLock();
				}
			}
			
			return result;
		}
	}
}
